#include <iostream>
#include <memory>

struct TestClass
{
    TestClass(int test)
    {
        _test = test;
    }
    int getVar() { return _test; }
    ~TestClass() {}
    int _test;
};
void func()
{
    std::shared_ptr<TestClass> test1 = std::make_shared<TestClass>(10);
    std::cout << test1.use_count() << std::endl; // 1

    std::weak_ptr<TestClass> weak1(test1);
    // weak_ptr不增加引用计数
    std::cout << test1.use_count() << std::endl; // 1

    // 检测对象存在
    if (weak1.expired())
        std::cout << "test1 expired" << std::endl;
    else
        std::cout << "test1 not expired" << std::endl;

    // 如果对象存在，就获取shared_ptr
    std::shared_ptr<TestClass> locked = weak1.lock();
    if (locked)
    {
        std::cout << locked->getVar() << std::endl; // 10
        // locked获取了weak_ptr，所以引用计数加1
        std::cout << test1.use_count() << std::endl; // 2
    }
    else
    {
        std::cout << "obj is not exists" << std::endl;
    }

    locked.reset();
    // 释放后，引用计数减少
    std::cout << test1.use_count() << std::endl; // 1

    test1.reset();
    std::cout << test1.use_count() << std::endl; // 0

    // 使用空shared_ptr构造weak_ptr
    std::weak_ptr<TestClass> weak2(test1);
    if (weak2.expired())
        std::cout << "weak2 expired" << std::endl;

    std::shared_ptr<TestClass> locked1 = weak2.lock();
    if (!locked1)
        std::cout << "weak2 观察的资源为空" << std::endl;
}
int main()
{
    // std::shared_ptr<TestClass> test1 = std::make_shared<TestClass>(10);
    // std::cout << test1.use_count() << std::endl; // 1

    // // 重载了 -> 和 * 运算符
    // std::cout << test1->getVar() << std::endl;   // 10
    // std::cout << (*test1).getVar() << std::endl; // 10

    // if (!test1.get())
    //     std::cout << "test1 is nullptr" << std::endl;
    // else
    //     std::cout << "test1 is not nullptr" << std::endl;

    // std::shared_ptr<TestClass> test2(test1); // 还支持 = 构造
    // std::shared_ptr<TestClass> test4 = test2;

    // // 测试资源是否转移
    // if (!test1.get())
    //     std::cout << "test1 is nullptr" << std::endl;
    // else
    //     std::cout << "test1 is not nullptr" << std::endl;

    // std::cout << test1.use_count() << std::endl; // 3
    // std::cout << test2->getVar() << std::endl;   // 10
    // std::cout << test2.use_count() << std::endl; // 3

    // std::shared_ptr<TestClass> test3 = std::make_shared<TestClass>(-1);
    // // 不能这样使用，会导致释放两次内存，程序崩溃
    // // 原因：test3的test2管理了同一份资源，换句话说，执行下面这个语句后
    // // test2和test3的引用计数都为1，程序结束释放资源时，一份资源就会被析构两次
    // // 程序就会崩溃
    // // test2.reset(test3.get());

    // // 正确做法，也可以不对test2初始化然后直接使用 = 运算符或者使用智能指针提供的swap方法
    // // 也可以使用std::move()进行资源所有权转移，智能指针支持移动语义
    // test2.reset();                  // 清空为nullptr
    // test2.reset(new TestClass(-2)); // 重新管理一个对象

    // std::cout << test2->getVar() << std::endl;   // -2
    // std::cout << test2.use_count() << std::endl; // 1
    // std::cout << test3.use_count() << std::endl; // 1

    // func();
    std::shared_ptr<TestClass> l = std::make_shared<TestClass>(10);
    std::shared_ptr<TestClass> l1(l);
    std::cout << l.use_count() << " " << l1.use_count() << std::endl;

    return 0;
}